#! /usr/bin/env bash

# 编译ffmpeg

set -e

# 当前执行脚本所在的文件夹
SCRIPT_DIR=$(cd "$(dirname "$0")";
pwd)

OS=$1
TARGET=$2
SOURCE_REPO=$3
BUILD_PATH=${BUILD_DIR}/${OS}
OUTPUT=${BUILD_PATH}/ffmpeg-${TARGET}
TOOLCHAIN_PATH=${BUILD_PATH}/toolchains/ffmpeg-${TARGET}

BUILD_OPT=

# 创建OUTPUT文件夹
mkdir -p ${OUTPUT}

cd ${SOURCE_REPO}

# 检测环境属性
. ${SCRIPT_DIR}/tools/do-detect-env.sh

# 目标平台
TARGET_API=${NDK_MIN_API}
# 交叉编译前缀
CROSS_PREFIX=
TOOLCHAIN_NAME=

# 第三方依赖
DEP_LIBS=
FDKAAC_BUILD_NAME=fdk-aac-${TARGET}
OPENH264_BUILD_NAME=openh264-${TARGET}
X264_BUILD_NAME=x264-${TARGET}

# 配置参数
CFLAGS="-O3 -Wall -pipe \
    -std=c99 \
    -ffast-math \
    -fstrict-aliasing -Werror=strict-aliasing \
    -Wno-psabi -Wa,--noexecstack \
    -DANDROID -DNDEBUG"

EXTRA_CFLAGS=
EXTRA_LDFLAGS=

FF_CFG_FLAGS=
. ${SCRIPT_DIR}/ffmpeg-config.sh
echo FF_CFG_FLAGS=${FF_CFG_FLAGS}

FF_MODULE_DIRS="compat libavcodec libavfilter libavformat libavutil libswresample libswscale"
FF_ASSEMBLER_SUB_DIRS=

# 根据生成目标配置参数
case ${TARGET} in

    armv5)
        CROSS_PREFIX=arm-linux-androideabi
        TOOLCHAIN_NAME=${CROSS_PREFIX}-${NDK_GCC_VER}

        FF_CFG_FLAGS="$FF_CFG_FLAGS --arch=arm"

        EXTRA_CFLAGS="$EXTRA_CFLAGS -march=armv5te -mtune=arm9tdmi -msoft-float"
        EXTRA_LDFLAGS="$EXTRA_LDFLAGS"

        FF_ASSEMBLER_SUB_DIRS="arm"
    ;;

    armv7a)
        CROSS_PREFIX=arm-linux-androideabi
        TOOLCHAIN_NAME=${CROSS_PREFIX}-${NDK_GCC_VER}

        FF_CFG_FLAGS="$FF_CFG_FLAGS --arch=arm --cpu=cortex-a8"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-neon"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-thumb"

        EXTRA_CFLAGS="$EXTRA_CFLAGS -march=armv7-a -mcpu=cortex-a8 -mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumb"
        EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,--fix-cortex-a8"

        FF_ASSEMBLER_SUB_DIRS="arm"
    ;;

    arm64)
    # android-21或以上平台才支持64位
        TARGET_API=21
        CROSS_PREFIX=aarch64-linux-android
        TOOLCHAIN_NAME=${CROSS_PREFIX}-${NDK_GCC_64_VER}

        FF_CFG_FLAGS="$FF_CFG_FLAGS --arch=aarch64 --enable-yasm"

        EXTRA_CFLAGS="$EXTRA_CFLAGS"
        EXTRA_LDFLAGS="$EXTRA_LDFLAGS"

        FF_ASSEMBLER_SUB_DIRS="aarch64 neon"
    ;;

    x86)
        CROSS_PREFIX=i686-linux-android
        TOOLCHAIN_NAME=${CROSS_PREFIX}-${NDK_GCC_VER}

        FF_CFG_FLAGS="$FF_CFG_FLAGS --arch=x86 --cpu=i686 --enable-yasm"

        EXTRA_CFLAGS="$EXTRA_CFLAGS -march=atom -msse3 -ffast-math -mfpmath=sse"
        EXTRA_LDFLAGS="$EXTRA_LDFLAGS"

        FF_ASSEMBLER_SUB_DIRS="x86"
    ;;

    x86_64)
    # android-21或以上平台才支持64位
        TARGET_API=21
        CROSS_PREFIX=x86_64-linux-android
        TOOLCHAIN_NAME=${CROSS_PREFIX}-${NDK_GCC_64_VER}

        FF_CFG_FLAGS="$FF_CFG_FLAGS --arch=x86_64 --enable-yasm"

        EXTRA_CFLAGS="$EXTRA_CFLAGS"
        EXTRA_LDFLAGS="$EXTRA_LDFLAGS"

        FF_ASSEMBLER_SUB_DIRS="x86"
    ;;

    *)
        echo "ffmpeg: 不支持编译'$TARGET'目标"
        exit 1
    ;;

esac

# make standalone toolchain
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh  \
 --platform=android-${TARGET_API}  \
 --toolchain=${TOOLCHAIN_NAME}  \
 --install-dir=${TOOLCHAIN_PATH}

FF_SYSROOT=${TOOLCHAIN_PATH}/sysroot

# fdk-aac
FDKAAC_INC=${BUILD_PATH}/${FDKAAC_BUILD_NAME}/include
FDKAAC_LIB=${BUILD_PATH}/${FDKAAC_BUILD_NAME}/lib
# openh264
OPENH264_INC=${BUILD_PATH}/${OPENH264_BUILD_NAME}/include
OPENH264_LIB=${BUILD_PATH}/${OPENH264_BUILD_NAME}/lib
# x264
X264_INC=${BUILD_PATH}/${X264_BUILD_NAME}/include
X264_LIB=${BUILD_PATH}/${X264_BUILD_NAME}/lib

echo "--------------------"
echo "[*] check ffmpeg env"
echo "--------------------"
export PATH=${TOOLCHAIN_PATH}/bin/:$PATH
export CC=${CROSS_PREFIX}-gcc
export LD=${CROSS_PREFIX}-ld
export AR=${CROSS_PREFIX}-ar
export STRIP=${CROSS_PREFIX}-strip

# with fdk-aac
if [[ -f "${FDKAAC_LIB}/libfdk-aac.a" ]]; then
    echo "libfdk-aac detected"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-libfdk-aac --enable-encoder=libfdk_aac --enable-decoder=libfdk_aac"

    CFLAGS="$CFLAGS -I$FDKAAC_INC"
    DEP_LIBS="$DEP_LIBS -L$FDKAAC_LIB -lfdk-aac -lm"
fi

# with openh264
if [[ -f "${OPENH264_LIB}/libopenh264.a" ]]; then
    echo "libopenh264 detected"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-libopenh264 --enable-encoder=libopenh264"

    CFLAGS="$CFLAGS -I$OPENH264_INC"
    # 用gcc编译C++源文件时，加以下选项：-lstdc++，否则使用了C++操作的文件编译会出错。
    # -lm -lz 也是必须要加上的
    DEP_LIBS="$DEP_LIBS -L$OPENH264_LIB -lopenh264 -lm -lz -lstdc++"

    # 解决问题：ERROR: openh264 not found using pkg-config
    # 参考：https://www.jianshu.com/p/36a8c73e3434
    export PKG_CONFIG_PATH=${OPENH264_LIB}/pkgconfig
    echo PKG_CONFIG_PATH=${PKG_CONFIG_PATH}
    ln -s ${SYS_PKG_CONFIG} ${TOOLCHAIN_PATH}/bin/${CROSS_PREFIX}-pkg-config
fi

# with x264
if [[ -f "${X264_LIB}/libx264.a" ]]; then
    echo "libx264 detacted"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-libx264 --enable-encoder=libx264 --enable-decoder=libx264"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-gpl --enable-nonfree"

    CFLAGS="$CFLAGS -I$X264_INC"
    DEP_LIBS="$DEP_LIBS -L$X264_LIB -lx264"
fi

#--------------------
# Standard options:
FF_CFG_FLAGS="$FF_CFG_FLAGS --prefix=$OUTPUT"

# Advanced options (experts only):
FF_CFG_FLAGS="$FF_CFG_FLAGS --cross-prefix=$CROSS_PREFIX-"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-cross-compile"
FF_CFG_FLAGS="$FF_CFG_FLAGS --target-os=linux"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-pic"
# FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-symver"

if [[ "$TARGET" = "x86" ]]; then
    FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-asm"
else
    # Optimization options (experts only):
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-asm"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-inline-asm"
fi

case "$BUILD_OPT" in
    debug)
        FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-optimizations"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-debug"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-small"
    ;;
    *)
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-optimizations"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-debug"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-small"
    ;;
esac

#--------------------
echo ""
echo "--------------------"
echo "[*] configurate ffmpeg"
echo "--------------------"
echo "./configure $FF_CFG_FLAGS"
echo --extra-cflags="$CFLAGS $EXTRA_CFLAGS"
echo --extra-ldflags="$DEP_LIBS $EXTRA_LDFLAGS"
which ${CC}
./configure ${FF_CFG_FLAGS}  \
 --extra-cflags="$CFLAGS $EXTRA_CFLAGS"  \
 --extra-ldflags="$DEP_LIBS $EXTRA_LDFLAGS"
make clean

#--------------------
echo ""
echo "--------------------"
echo "[*] compile ffmpeg"
echo "--------------------"
cp config.* ${OUTPUT}
make -j
make install
mkdir -p ${OUTPUT}/include/libffmpeg
cp -f config.h ${OUTPUT}/include/libffmpeg/config.h

#--------------------
echo ""
echo "--------------------"
echo "[*] link ffmpeg"
echo "--------------------"
echo ${EXTRA_LDFLAGS}

FF_C_OBJ_FILES=
FF_ASM_OBJ_FILES=
for MODULE_DIR in ${FF_MODULE_DIRS}
do
    C_OBJ_FILES="$MODULE_DIR/*.o"
    if ls ${C_OBJ_FILES} 1> /dev/null 2>&1; then
        echo "link $MODULE_DIR/*.o"
        FF_C_OBJ_FILES="$FF_C_OBJ_FILES $C_OBJ_FILES"
    fi

    for ASM_SUB_DIR in ${FF_ASSEMBLER_SUB_DIRS}
    do
        ASM_OBJ_FILES="$MODULE_DIR/$ASM_SUB_DIR/*.o"
        if ls ${ASM_OBJ_FILES} 1> /dev/null 2>&1; then
            echo "link $MODULE_DIR/$ASM_SUB_DIR/*.o"
            FF_ASM_OBJ_FILES="$FF_ASM_OBJ_FILES $ASM_OBJ_FILES"
        fi
    done
done

${CC} -lm -lz -shared --sysroot=${FF_SYSROOT} -Wl,--no-undefined -Wl,-z,noexecstack ${EXTRA_LDFLAGS}  \
 -Wl,-soname,libffmpeg.so  \
 ${FF_C_OBJ_FILES}  \
 ${FF_ASM_OBJ_FILES}  \
 ${DEP_LIBS}  \
 -o ${OUTPUT}/libffmpeg.so

mysedi() {
    f=$1
    exp=$2
    n=`basename ${f}`
    cp ${f} /tmp/${n}
    sed ${exp} /tmp/${n} > ${f}
    rm /tmp/${n}
}

echo ""
echo "--------------------"
echo "[*] create files for shared ffmpeg"
echo "--------------------"
rm -rf ${OUTPUT}/shared
mkdir -p ${OUTPUT}/shared/lib/pkgconfig
ln -s ${OUTPUT}/include ${OUTPUT}/shared/include
ln -s ${OUTPUT}/libffmpeg.so ${OUTPUT}/shared/lib/libffmpeg.so
cp ${OUTPUT}/lib/pkgconfig/*.pc ${OUTPUT}/shared/lib/pkgconfig
for f in ${OUTPUT}/lib/pkgconfig/*.pc; do
    # in case empty dir
    if [[ ! -f ${f} ]]; then
        continue
    fi
    cp ${f} ${OUTPUT}/shared/lib/pkgconfig
    f=${OUTPUT}/shared/lib/pkgconfig/`basename ${f}`
    # OSX sed doesn't have in-place(-i)
    mysedi ${f} 's/\/output/\/output\/shared/g'
    mysedi ${f} 's/-lavcodec/-lffmpeg/g'
    mysedi ${f} 's/-lavfilter/-lffmpeg/g'
    mysedi ${f} 's/-lavformat/-lffmpeg/g'
    mysedi ${f} 's/-lavutil/-lffmpeg/g'
    mysedi ${f} 's/-lswresample/-lffmpeg/g'
    mysedi ${f} 's/-lswscale/-lffmpeg/g'
done